package org.myspringframework.core;


import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class ClassPathXmlApplicationContext implements ApplicationContext {

    private static final Logger logger = LoggerFactory.getLogger(ClassPathXmlApplicationContext.class);

    private Map<String,Object> singletonObjects =new HashMap<>();


    //解析myspring的配置文件，然后初始化所有bean对象
    public ClassPathXmlApplicationContext(String configlocation) {
        try {
            // 这是dom4j解析XML文件的核心对象
            SAXReader reader=new SAXReader();
            //获取一个输入流

            InputStream in = ClassLoader.getSystemClassLoader().getResourceAsStream(configlocation);

            Document document = reader.read(in);
            System.out.println(document);
            //获取所有的bean标签
            List<Node> nodes = document.selectNodes("//bean");

            //遍历bean标签
            nodes.forEach(node -> {
                try {



                    Element beanElt = (Element) node;
                    String id = beanElt.attributeValue("id");
                    String className = beanElt.attributeValue("class");
                    logger.info("beanName=" + id);
                    logger.info("beanClassName=" + className);

                    Class<?> aClass = Class.forName(className);

                    Constructor<?> defaultCon = aClass.getDeclaredConstructor();

                    Object bean =defaultCon.newInstance();

                    singletonObjects.put(id,bean);

                    logger.info(singletonObjects.toString());
                }catch (Exception e){
                    e.printStackTrace();
                }

            });
            nodes.forEach(node -> {
                try {
                    Element beanElt=(Element) node;

                    String id =beanElt.attributeValue("id");
                    String className = beanElt.attributeValue("class");

                    Class<?> aClass =Class.forName(className);
                    List<Element> propertys = beanElt.elements("property");

                    propertys.forEach(property->{
                        try {
                            String propertyName=property.attributeValue("name");
                            logger.info("属性名"+propertyName);
                            Field field = aClass.getDeclaredField(propertyName);
                            String setMethodName ="set"+ propertyName.toUpperCase().charAt(0)+propertyName.substring(1);

                            Method setMethod =aClass.getDeclaredMethod(setMethodName,field.getType());
                            String value = property.attributeValue("value");
                            Object actualValue =null;//真值
                            String ref = property.attributeValue("ref");
                            if (value !=null) {
                                String propertyTypeSimpleName = field.getType().getSimpleName();
                                switch (propertyTypeSimpleName){
                                    case "byte":
                                        actualValue =Byte.parseByte(value);
                                        break;
                                    case "short":
                                        actualValue =Short.parseShort(value);
                                        break;
                                    case"int":
                                        actualValue =Integer.parseInt(value);
                                        break;
                                    case "long":
                                        actualValue =Long.parseLong(value);
                                        break;
                                    case "flaot":
                                        actualValue =Float.parseFloat(value);
                                        break;
                                    case "double":
                                        actualValue =Double.parseDouble(value);
                                        break;
                                    case "boolean":
                                    case "char":
                                    case "Byte":
                                        case "Short":
                                    case "Integer":
                                    case "Long":
                                    case "Float":
                                    case "Double":
                                    case "Boolean":
                                    case "Character":
                                        actualValue= Character.valueOf(value.charAt(0));
                                    case "String":
                                }
                                setMethod.invoke(singletonObjects.get(id),value);
                            }
                            if (ref !=null) {
                                setMethod.invoke(singletonObjects.get(id),singletonObjects.get(ref));
                            }
                            //难点：是怎样区分两个value 还是 ref

                        }catch (Exception e){
                            e.printStackTrace();
                        }

                    });
                }catch (Exception e){
                    e.printStackTrace();
                }

            });
        }catch (Exception e){
            e.printStackTrace();
        }


    }

    @Override
    public Object getBean(String beanName) {
        return singletonObjects.get(beanName);
    }
}
